package com.ae.shield.common.gui.container;

import com.ae.shield.common.block.BlockList;
import com.ae.shield.common.block.tile.AssemblyTile;
import net.minecraft.entity.player.PlayerEntity;
import net.minecraft.entity.player.PlayerInventory;
import net.minecraft.inventory.container.Container;
import net.minecraft.inventory.container.Slot;
import net.minecraft.item.ItemStack;
import net.minecraft.network.PacketBuffer;
import net.minecraft.util.IWorldPosCallable;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.text.ITextComponent;
import net.minecraft.world.World;
import net.minecraftforge.api.distmarker.Dist;
import net.minecraftforge.api.distmarker.OnlyIn;
import net.minecraftforge.fluids.capability.IFluidHandler;
import net.minecraftforge.items.SlotItemHandler;

import javax.annotation.Nonnull;

public class AssemblyContainer extends Container {
    private final IWorldPosCallable callable;
    private final AssemblyTile blockTile;

    public AssemblyContainer(int id, PlayerInventory playerInventory, BlockPos pos) {
        super(ContainerList.ASSEMBLY_CONTAINER.get(), id);
        World world = playerInventory.player.world;
        this.callable = IWorldPosCallable.of(world, pos);
        this.blockTile = (AssemblyTile) world.getTileEntity(pos);
        loadSlot(playerInventory);
    }

    public AssemblyContainer(int id, PlayerInventory playerInventory, PacketBuffer buffer) {
        this(id, playerInventory, buffer.readBlockPos());
    }

    @Nonnull
    @Override
    public ItemStack transferStackInSlot(@Nonnull PlayerEntity playerIn, int slotIn) {
        ItemStack stack;
        Slot slot = inventorySlots.get(slotIn);

        if (slot == null || !slot.getHasStack()) {
            return ItemStack.EMPTY;
        }

        ItemStack itemStack = slot.getStack();
        stack = itemStack.copy();
        int invStart = 0;
        int invEnd = invStart + 27;
        int shortEnd = invEnd + 9;
        int inEnd = shortEnd + blockTile.getInventory().getSlots();

        if (slotIn < shortEnd) {
            if (!mergeItemStack(itemStack, shortEnd, inEnd, false)) {
                return ItemStack.EMPTY;
            }
        } else {
            if (!mergeItemStack(itemStack, invEnd, shortEnd, false) && !mergeItemStack(itemStack, invStart, invEnd, false)) {
                return ItemStack.EMPTY;
            }
        }

        if (itemStack.isEmpty()) {
            slot.putStack(ItemStack.EMPTY);
        } else {
            slot.onSlotChanged();
        }

        if (itemStack.getCount() == stack.getCount()) {
            return ItemStack.EMPTY;
        }

        slot.onTake(playerIn, itemStack);

        return stack;
    }

    private void loadSlot(PlayerInventory playerInv) {
        //创建玩家背包
        for (int row = 0; row < 3; row++) {
            for (int column = 0; column < 9; column++) {
                addSlot(new Slot(playerInv, column + row * 9 + 9, 8 + column * 18, 116 + row * 18));
            }
        }
        //创建工具栏
        for (int col = 0; col < 9; ++col) {
            addSlot(new Slot(playerInv, col, 8 + col * 18, 174));
        }
        //创建材料格
        addSlot(new SlotItemHandler(blockTile.getInventory(), 0, 73, 51));
        for (int i = 0; i < 3; i++) {
            addSlot(new SlotItemHandler(blockTile.getInventory(), i + 1, 55 + 18 * i, 15));
        }
        for (int i = 0; i < 3; i++) {
            addSlot(new SlotItemHandler(blockTile.getInventory(), i + 4, 109, 33 + 18 * i));
        }
        for (int i = 0; i < 3; i++) {
            addSlot(new SlotItemHandler(blockTile.getInventory(), i + 7, 91 - 18 * i, 87));
        }
        for (int i = 0; i < 3; i++) {
            addSlot(new SlotItemHandler(blockTile.getInventory(), i + 10, 37, 69 - 18 * i));
        }
        //产物格
        addSlot(new SlotItemHandler(blockTile.getOut(), 0, 138, 51) {
            @Override
            public boolean isItemValid(@Nonnull ItemStack stack) {
                return false;
            }

            @Override
            public void onSlotChange(@Nonnull ItemStack oldStackIn, @Nonnull ItemStack newStackIn) {
                PlayerEntity player = playerInv.player;
                World world = player.world;
                if (!world.isRemote) {
                    oldStackIn.onCrafting(world, player, oldStackIn.getCount());
                }
            }
        });
    }

    @Override
    public boolean canInteractWith(@Nonnull PlayerEntity playerIn) {
        return isWithinUsableDistance(callable, playerIn, BlockList.ASSEMBLY_BLOCK.get());
    }

    @OnlyIn(Dist.CLIENT)
    public float getProgressionScaled() {
        int i = blockTile.getLastTick();
        int j = blockTile.getTick();
        return i == 0 || j == 0 ? 0 : (float) j / i;
    }

    public boolean isWorking() {
        return blockTile.getTick() > 0;
    }

    public IFluidHandler getTank() {
        return blockTile.getTank();
    }

    @OnlyIn(Dist.CLIENT)
    public float getEnergyScaled() {
        int i = blockTile.getEnergy().getMaxEnergyStored();
        int j = blockTile.getEnergy().getEnergyStored();
        return i == 0 || j == 0 ? 0 : (float) j / i;
    }

    @OnlyIn(Dist.CLIENT)
    public int getEnergy() {
        return blockTile.getEnergy().getEnergyStored();
    }

    @OnlyIn(Dist.CLIENT)
    public float getFluidScaled() {
        int i = blockTile.getTank().getTankCapacity(0);
        int j = blockTile.getTank().getFluidInTank(0).getAmount();
        return i == 0 || j == 0 ? 0 : (float) j / i;
    }

    public ITextComponent getDisplayName() {
        return blockTile.getDisplayName();
    }
}
